var events = require('events');
var util = require('util');
var hashTable = require('../common/hashtable.js');

var MODNAME = 'EventManager';

var EventManager = function(pAppObj) {
	events.EventEmitter.call(this);
	this._EventList = hashTable.create();
	this.XAPPOBJ = pAppObj;
	this.logger = pAppObj.XLOGGER;
	
};
EventManager.prototype.close = function () {
	this._EventList.clear();
};

util.inherits(EventManager, events.EventEmitter);

EventManager.prototype.add = function (pSubsObj, pEventName, pEventHandler, pAllowMultiSubscrptions) {
	pEventName = pEventName.toUpperCase();
	var status = false;
	var subsConfigObj = pSubsObj._Config;
	subsConfigObj.TYPE = "APP";
	
	//TODO: need to know the type of subsobj
	
	
	//this.logger.log(MODNAME, 'INFO_LEVEL_3','Checking whether the event ['+pEventName+'] is already exist in the EventStack');
	var eventObj = this._EventList.getItem(pEventName);
	if (eventObj) {
		this.logger.log(MODNAME, 'INFO_LEVEL_3','Found Event in the EventStack');
		if (!eventObj.MULTISUBSCRIPTIONS){			
			var owner = eventObj.SUBSCRIBERS[0];
			this.logger.log(MODNAME, 'ERROR', 'MultiSubscriptions are disabled for EVENTNAME: '+pEventName+', REQUESTED-SUBSCRIBER: ['+ subsConfigObj.NAME +'] by the Owner [NAME:'+owner.NAME+']');
			return status;
		}
		
		//Add subscriber to the existed event
		var sObj = {'NAME': subsConfigObj.NAME, 'TYPE': subsConfigObj.TYPE, "ISOWNER": false};
		eventObj.SUBSCRIBERS.push(sObj);
		this.logger.log(MODNAME, 'INFO_LEVEL_3','Subscribed to the ['+pEventName+']');
				
	} else {
		this.logger.log(MODNAME, 'INFO_LEVEL_3','Not available in the EventStack');
		//create new event
		eventObj = {
				'EVENTNAME': pEventName,
				'SUBSCRIBERS':	[],
				'MULTISUBSCRIPTIONS': pAllowMultiSubscrptions,
		};
		this.logger.log(MODNAME, 'INFO_LEVEL_3','Created New Event: ['+pEventName+'] with ['+subsConfigObj.NAME+'] as owner');
		//Add subscriber to the new event
		var sObj = {'NAME': subsConfigObj.NAME, 'TYPE': subsConfigObj.TYPE , "ISOWNER": true};		
		eventObj.SUBSCRIBERS.push(sObj);
		this.logger.log(MODNAME, 'INFO_LEVEL_3','Subscribed to the ['+pEventName+']');
		
		this._EventList.setItem(pEventName, eventObj);
	}
	
	//this.logger.log(MODNAME, 'INFO_LEVEL_3','Registered the handler to the ['+pEventName+']');
	// register the event
	this.on(pEventName, (pEventHandler).bind(pSubsObj));
	status = true;
	
	return status;
};

EventManager.prototype.remove = function (pEventName) {
	
	this._EventList.removeItem(pEventName);
	this.logger.log(MODNAME, 'INFO_LEVEL_3','Removed the event');
};

EventManager.prototype.dispatchEvent = function (pMngrObj, pEvent) {
		
	var eventName = pEvent.getEventName();
	this.logger.log(MODNAME, 'INFO_LEVEL_2','Rcvd Event ['+eventName+'] from Kernel......');
	//this.logger.log(MODNAME, 'INFO_LEVEL_2','Dispatching ['+eventName+'], Payload: '+JSON.stringify(pEvent)+']');
	
	/*
	var index = eventName.indexOf('.');
	if (index === 0){
		
	} else if (index > 0) {
		eventName = eventName.substring(0,index);
	}
	*/
	var eventObj = this._EventList.getItem(eventName);
	if (eventObj) {
		//this.logger.log(MODNAME, 'INFO_LEVEL_3','Handler found for the event ['+eventName+']');
		//setTimeout(function(){console.log('delay of 1 sec happens')}, 1000);
		//this.emit(eventName, pEvent);
		var self = this;
		setTimeout(function() {
			 self.emit(eventName, pEvent);
			 }, 1);
		this.logger.log(MODNAME, 'INFO_LEVEL_2','Dispatched event ['+eventName+'], Payload: '+JSON.stringify(pEvent)+']');
		//this.logger.log(MODNAME, 'INFO_LEVEL_2','Dispatched to subscriber which handles ['+eventName+'] events');
	}
	else {
		this.logger.log(MODNAME, 'INFO_LEVEL_2','No handler found for the event ['+eventName+']');
	}
};

EventManager.prototype.getEventsList = function () {
	return this._EventList;
};
EventManager.prototype.printEventsList = function () {
	console.log(this._EventList);
};

exports.create = function(pObj) { return new EventManager(pObj); };